package main;


	

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;

	//电脑下棋类
	public class AI {
		//电脑走一步
		public static boolean next(GamePanel panel) {
			Boolean flag= go(panel)|| luoziRandom(panel);//短路,前面返回的值决定后面要不要走
			return flag;
		}
		//判断五子连珠
		static boolean has5(Pointer pointer1,GamePanel panel){
			List<Data> datas=new ArrayList<Data>();
			//循环找出黑棋，判断此棋子的1横向 2纵向 3右捺 4左撇 是否有四子的情况
			Pointer pointer;
			for(int i=0;i<panel.ROWS;i++){
				for(int j=0;j<panel.COLS;j++){
					pointer= panel.pointers[i][j];
					if(pointer==null)continue;
					if(pointer.getType()==0){//没有棋子则跳过
						continue;
					}
					if(pointer1.getType()!=pointer.getType()){
						continue;
					}
					//循环四个方向
					int dir =1;
					for(int k=1;k<=4;k++){
						dir=k;
						Data data=getData(dir,1,panel,pointer);
						if(data.getCount()!=-1&&data.getCount()!=0){//0和-1的过滤掉
							datas.add(data);
						}
						data=getData(dir,1,panel,pointer);
						if(data.getCount()!=-1&&data.getCount()!=0){//0和-1的过滤掉
							datas.add(data);
						}
					}
				}
			}
			//按权重分排序处理，从大到小
			Collections.sort(datas,new DataCount());
			if(datas.size()>0){//取第一个位置
				Data data=datas.get(0);
				if(data.getCount()==100){
					return true;
				}
			}
			return false;
		}
		//电脑通过计算走下一步
		private static boolean go(GamePanel panel){
			/*
			1循环指示器
			2.循环四个方向
			3.分别计算从左往右、从右往左，并将返回的结果放到集合中（有效的才放）
			4.对权重分别进行排序处理，把最大的排到最前面
			5.取第一个元素作为落子的地方，并返回true
			*/
			List<Data>datas= new ArrayList<Data>();//将返回的结果放到集合中
			Pointer[][]pointers=panel.pointers;
			//1.循环指示器
			Pointer pointer;
			Data data;
			for(int i=0;i<panel.ROWS;i++){
				for(int j=0;j<panel.COLS;j++){
					pointer=pointers[i][j];
					if(pointer==null || pointer.getType()==0)
						continue;
					 int dir=0;
					 for(int k=1;k<=4;k++){
					 	dir=k;
					 	//获取权重分1
					 	data=getData(dir,1,panel,pointer);
					 	if(data.getCount()!=0&&data.getCount()!=-1){
					 		//添加到集合中
					 	     datas.add(data);
					 	}
					 	
					 	//获取权重分2
					    data=getData(dir,2,panel,pointer);
					    if (data.getCount()!=0&&data.getCount()!=-1) {
					    	//添加到集合中
					 	    datas.add(data);
					    }
					 	
					 	
					 }

				}
			}
			//排序
			Collections.sort(datas,new DataCount());
			for(int i=0;i<datas.size();i++){
				System.out.println("权重分："+datas.get(i).getCount());
			}
			if(datas.size()>0){
				Data data2=datas.get(0);
				Pointer pointer1=pointers[data2.getI()][data2.getJ()];
				luozi(pointer1, 1, panel);
				
				return true;
			}

			return false;
		}

		//获取权重分
		private static Data getData(int dir,int type,GamePanel panel,Pointer pointer){
			//返回结果
			Data resData=new Data();
			int i=pointer.getI();
			int j=pointer.getJ();

	        Pointer[][]pointers=panel.pointers;
	        Pointer temPointer;

	        int num=1;//计算分数用的num
	        int num2=1;//累计相同的num
	        boolean breakFlag=false;//是否中断

	        boolean lClosed=false;//左关闭
	        boolean rClosed=false;//右关闭

			//横向
			if(dir==1){
				//从左到右
				if(type==1){
					for(int k=j+1;k<panel.COLS;k++){
						temPointer=pointers[i][k];//拿到循环的每一个元素（指示器元素）
						if(temPointer.getType()==pointer.getType()){//连续的
							num++;
							num2++;
							if(k==panel.COLS-1){
								rClosed=true;
							}

						}else if(temPointer.getType()==0){//空白
							if(breakFlag){
								//判断前一个子是否是空白
								if(pointers[i][k-1].getType()==0){//如果是空白
									breakFlag=false;
								}
								break;
							}
							num++;
							breakFlag=true;
							resData.setI(i);
							resData.setJ(k);

						}else{//对立
							rClosed=true;
							break;
						}
						//处理左关闭
						if(j==0){
							lClosed=true;
						}
						else {
							if(pointers[i][j-1].getType()!=0){
								lClosed=true;

							}
						}
					}

					}else{//从右往左
						for(int k=j-1;k>=0;k--){
						temPointer=pointers[i][k];//拿到循环的每一个元素（指示器元素）
						if(temPointer.getType()==pointer.getType()){//连续的
							num++;
							num2++;
							if(k==0){
								lClosed=true;
							}

						}else if(temPointer.getType()==0){//空白
							if(breakFlag){
								//判断前一个子是否是空白
								if(pointers[i][k+1].getType()==0){//如果是空白
									breakFlag=false;
								}
								break;
							}
							num++;
							breakFlag=true;
							resData.setI(i);
							resData.setJ(k);

						}else{//对立
							lClosed=true;
							break;
						}
						//处理右关闭
						if(j==panel.COLS-1){
							rClosed=true;
						}
						else {
							if(pointers[i][j+1].getType()!=0){
								rClosed=true;

							}
						}
					}

				}
			}else if (dir==2) {//竖向
				//往下循环，判断能与当前pointer相同的棋子连续多少个
				if(type==1){
					for(int k=i+1;k<panel.ROWS;k++){
						temPointer=pointers[k][j];
						if(temPointer.getType()==pointer.getType()){//连续
							num++;
							num2++;
							if(k==panel.ROWS-1){//如果最后一个子也是连续的，则也是右关闭的
								rClosed=true;
							}

						}else if(temPointer.getType()==0){//空白子
							if(breakFlag){//有一个则不能通过了
								if(pointers[k-1][j].getType()==0){//如果前一个是空子，要设置成不是中断的
									breakFlag=true;;
								}
								break;
							}
							breakFlag=true;;
							num++;
							//是中断的那种，这里设定好落子位置
							resData.setI(k);
							resData.setJ(j);
						}else{//对立子，右关闭
							rClosed=true;
							break;
						}
					}
					//判断是否左关闭
					if (i==0) {//当前子就是最左边的子
						lClosed=true;
						
					}else {
						temPointer=pointers[i-1][j];
						if(temPointer.getType()!=0){//如果当前子的左边有子，则左关闭
							lClosed=true;
						}
					}
				}else{//从右往左
					for(int k=i-1;k>=0;k--){
						temPointer=pointers[k][j];
						if(temPointer.getType()==pointer.getType()){//连续
							num++;
							num2++; 
							if(k==0){//如果最后一个子也是连续的，则也是左关闭的
								lClosed=true;
							}
						}else if (temPointer.getType()==0) {//空白子
							if(breakFlag){//有一个则不能通过了
								if (pointers[k+1][j].getType()==0) {//如果前一个是空子，要设置成不是中断的
									breakFlag=false;;
								}
								break;
							}
							breakFlag=true;;
							num++;
							//是中断的那种，这里设定好落子位置
							resData.setI(k);
							resData.setJ(j);
							
						}else{//对立子，左关闭
							lClosed=true;
							break;
						}
					}
					//判断是否右关闭
					if(i==panel.ROWS-1){//当前子就是最右边的子
						rClosed=true;
					}else{
						temPointer=pointers[i+1][j];
						if(temPointer.getType()!=0){//如果当前子的右边有子，则右关闭
							rClosed=true;
						}

						}
					}
				}else if (dir==3) {//右捺
					//往右循环，判断能与当前pointer相同的棋子连续多少个
					int tempi=i;
					if(type==1){
						for(int k=j+1;k<panel.COLS;k++){
							tempi++;
							if(tempi>panel.COLS-1){//超出边界，设置为关闭的
								rClosed=true;
								break;
							}
							temPointer=pointers[tempi][k];
							if(temPointer.getType()==pointer.getType()){//连续
								num++;
								num2++;
								if(k==panel.COLS-1){//如果最后一个子也是连续的，则也是右关闭的
									rClosed=true;
								}
							}else if(temPointer.getType()==0){//空白子
								if(breakFlag){//有一个则不能通过了
									if(pointers[tempi-1][k-1].getType()==0){//如果前一个是空子，要设置成不是中断的
										breakFlag=false;;

									}
									break;
								}
								breakFlag=true;;
								num++;
								//也是中断的那种，这里设定好落子位置
								resData.setI(tempi);
								resData.setJ(k);
							}else{//对立子，右关闭
								rClosed=true;
								break;
							}
						}
						//判断是否左关闭
						if(j==0||i==0){//当前子就是最边上的子
							lClosed=true;
						}else{
							temPointer=pointers[i-1][j-1];
							if(temPointer.getType()!=0){//如果当前子的左边有子，则左关闭
								lClosed=true;
							}
						}
					}else{//从右往左
						for(int k=j-1;k>=0;k--){
							tempi--;
							if(tempi<0){
								lClosed=true;
								break;
							}
							temPointer=pointers[tempi][k];
							if(temPointer.getType()==pointer.getType()){//连续
								num++;
								num2++;
								if(k==0){//如果最后一个子也是连续的，则也是左关闭的
									lClosed=true;
								}
							}else if(temPointer.getType()==0){//空白子
								if(breakFlag){//有一个则不能通过了
									if(pointers[tempi+1][k+1].getType()==0){//如果前一个是空子·，要设置成不是中断的
										breakFlag=false;;
									}
									break;
								}
								breakFlag=true;;
								num++;
								//是中断的那种，这里设定好落子位置
								resData.setI(tempi);
								resData.setJ(k);
							}else{//对立子，左关闭
								lClosed=true;
								break;
							}
						}
						//判断是否右关闭
						if(j==panel.COLS-1||i==panel.ROWS-1){//当前子就是最边的子
							rClosed=true;
						}else{
							temPointer=pointers[i+1][j+1];
							if(temPointer.getType()!=0){//如果当前的右边有子，则右关闭
								rClosed=true;
							}
						}
					}
					
				}else if(dir==4){//左撇
					//往右循环，判断能与当前pointer相同的棋子连续多少个
					int tempi=i;
					if(type==1){
						for(int k=j+1;k<panel.ROWS;k++){
							tempi--;
							if(tempi<0){
								rClosed=true;
								break;
							}
							temPointer=pointers[tempi][k];
							if(temPointer.getType()==pointer.getType()){//连续
								num++;
								num2++;
								if(k==panel.COLS-1){//如果最后一个子也是连续的，则也是右关闭的
									rClosed=true;
								}
							}else if(temPointer.getType()==0){//空白子
								if(breakFlag){//有一个则不能通过了
									if(pointers[tempi+1][k-1].getType()==0){//如果前一个是空子，要设置成不是中断的
										breakFlag=false;;

									}
									break;
								}
								breakFlag=true;;
								num++;
								//也是中断的那种，这里设定好落子位置
								resData.setI(tempi);
								resData.setJ(k);
							}else{//对立子，右关闭
								rClosed=true;
								break;
							}
						}
						//判断是否左关闭
						if(j==0||i==0){//当前子就是最边上的子
							lClosed=true;
						}else{
							if(i==panel.ROWS-1){
								lClosed=true;
							}else{
								temPointer=pointers[i+1][j-1];
								if(temPointer.getType()!=0){//如果当前子的左边有子，则左关闭
								lClosed=true;
							}
								
						}
					}
				}else{//从右往左
						for(int k=j-1;k>=0;k--){
							tempi++;
							if(tempi>panel.ROWS-1){//超出边界，设置为关闭的
								lClosed=true;
								break;
							}
							temPointer=pointers[tempi][k];
							if(temPointer.getType()==pointer.getType()){//连续
								num++;
								num2++;
								if(k==0){//如果最后一个子也是连续的，则也是左关闭的
									lClosed=true;
								}
							}else if(temPointer.getType()==0){//空白子
								if(breakFlag){//有一个则不能通过了
									if(pointers[tempi-1][k+1].getType()==0){//如果前一个是空子·，要设置成不是中断的
										breakFlag=false;;
									}
									break;
								}
								breakFlag=true;
								num++;
								//是中断的那种，这里设定好落子位置
								resData.setI(tempi);
								resData.setJ(k);
							}else{//对立子，左关闭
								lClosed=true;
								break;
							}
						}
						//判断是否右关闭
						if(j==panel.COLS-1||i==panel.ROWS-1){//当前子就是最边的子
							rClosed=true;
						}else{
							if(i==0){
								rClosed=true;
							}else{
								temPointer=pointers[i-1][j+1];
							if(temPointer.getType()!=0){//如果当前的右边有子，则右关闭
								rClosed=true;
							}
						}
					}

				}
				
			}
			//设定分数
			setCount(resData,i,j,dir,type,num,num2,breakFlag,lClosed,rClosed,panel);
			return resData;
		}
		//设定分数
		private static void setCount(Data resData,int i,int j,int dir,int type, int num,int num2,
			boolean breakFlag,boolean lClosed,boolean rClosed,GamePanel panel){
			//计算的分数
			int count=0;

			if(num<=2){
				return ;
			}
			//分数的初步设定
			if(num==3){
				count=30;
			}else if(num==4){
				count=40;
			}
			else if(num==5){
				count=50;
			}

			//五子的情况处理，如果五子 设定分数为100
			if(num2>=5&&!breakFlag){
				count=100;
				resData.setCount(100);
				return;
			}


			if(breakFlag){//如果是中断的
				if(lClosed&&rClosed){
					count=-1;
				}

			}else{//连续的
				if(lClosed&&rClosed){//如果没有中断，并且左右都关闭了，则分数为-1，-1表示落子的时候要过滤掉
					count=-1;
				}else if(!lClosed){//如果是中断的那种，左边未关闭
					count+=2;//加2分
					
					if(dir==1){
						
						if(type==1){
							resData.setI(i);
							resData.setJ(j-1);
						}else {
							resData.setI(i);
							resData.setJ(j-num+1);
						}
					
				    }else if(dir==2){
				    	if(type==1){
							resData.setI(i-1);
							resData.setJ(j);
						}else {
							resData.setI(i-num+1);
							resData.setJ(j);
						}
					
				    }else if(dir==3){
				    	if(type==1){
							resData.setI(i-1);
							resData.setJ(j-1);
						}else {
							resData.setI(i-num+1);
							resData.setJ(j-num+1);
						}
					
				    }else if(dir==4){
				    	if(type==1){
							resData.setI(i+1);
							resData.setJ(j-1);
						}else {
							resData.setI(i+num-1);
							resData.setJ(j-num+1);
						}
					
				    }
				}else if(!rClosed){//如果是中断的那种，右边未关闭
					count+=1;//加1分
					if(dir==1){
						
						if(type==1){
							resData.setI(i);
							resData.setJ(j+num-1);
						}else {
							resData.setI(i);
							resData.setJ(j+1);
						}
					
				    }else if(dir==2){
				    	if(type==1){
							resData.setI(i+num-1);
							resData.setJ(j);
						}else {
							resData.setI(i+1);
							resData.setJ(j);
						}
					
				    }else if(dir==3){
				    	if(type==1){
							resData.setI(i+num-1);
							resData.setJ(j+num-1);
						}else {
							resData.setI(i+1);
							resData.setJ(j+1);
						}
					
				    }else if(dir==4){
				    	if(type==1){
							resData.setI(i-num+1);
							resData.setJ(j+num-1);
						}else {
							resData.setI(i-1);
							resData.setJ(j+1);
						}
					
				    }
					
				}

			}
			resData.setCount(count);
		}

		//随机落子
		private static Boolean luoziRandom(GamePanel panel) {
			// TODO Auto-generated method stub
			//获取指示器的位置
			Pointer pointer = getRandomPointer(panel);
			
			//根据位置来进行落子
			luozi(pointer,1,panel);
			return false;
		}
		
		//根据位置来进行落子
		private static void luozi(Pointer pointer, int type, GamePanel panel) {
			// TODO Auto-generated method stub
			//创建对象
			QiZi qizi = new QiZi(pointer.getX(),pointer.getY(),type);
			
			//将棋子添加到集合中
			qizi.setLast(true);
			panel.qizis.add(qizi);
			
			//给指示器设置类型
			pointer.setType(type);
			
			//重绘
			panel.repaint();
			
			if(has5(pointer,panel)){
				//失败
				panel.gameOver();
			}
			


		}
		//随机获取指示器位置
		private static Pointer getRandomPointer(GamePanel panel) {
			// TODO Auto-generated method stub
			Random random = new Random();
			int i=random.nextInt(panel.ROWS);//0-14
			int j=random.nextInt(panel.COLS);//0-14
			//获取到对应位置的指示器对象
			Pointer pointer = panel.pointers[i][j];
			
			if(pointer.getType()!=0) {//如果不是空白，则需要重新获取（递归）
				return getRandomPointer(panel);
			}
			return pointer;
		}
	}
	//自定义排序类
	class DataCount implements Comparator<Data>{
		public int compare(Data o1,Data o2){
			if(o1.getCount()>o2.getCount()){
				return -1;
			}
			return 0;

	}
	}
